package com.app.util;

import java.security.PublicKey;
import java.util.ArrayList;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.AbstractMap.SimpleEntry;
import java.util.Map.Entry;

import android.app.Activity;
import android.app.Fragment;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.View;

/**
 * 
 * @author Nick
 *         Application Mediator that controls all the communication among
 *         fragments and activities. It uses the Singleton pattern, so it can't
 *         be instantiated with the "new" word because there can be only one
 *         instance for application.
 *         To instantiate this class it is necessary to use the getInstance()
 *         method.
 *         It's possible to modify this class in order to being able to pass
 *         custom objects.
 * 
 */
public class ApplicationMediator {
	private static final boolean DEBUG = true;
	private static final String TAG = "APPLICATIONMEDIATOR";

	private static ApplicationMediator instance;
	private DoubleLevelWeakHashMap<String, Object, MessageListenerAdapter> mMap;

	/**
	 * The right way to get an instance of this class is with the method
	 * getInstance();
	 */
	private ApplicationMediator() {
		mMap = new DoubleLevelWeakHashMap<String, Object, MessageListenerAdapter>();
	}

	/**
	 * Method used to get the instance of this class.
	 * 
	 * @return the Mediator Instance
	 */
	public static ApplicationMediator getInstance() {
		if (instance == null) {
			instance = new ApplicationMediator();
		}
		return instance;
	}

	/**
	 * Set a listener for the given key.
	 * Example:
	 * Mediator.getInstance().setMessageListener(mActivity,mKey,new MessageListenerAdapter() {
	 * 		@Override
	 *  	public void onMessageRecevied(){
	 *  	//CUSTOM CODE
	 *  	}
	 *  }
	 * @param activity The activity from which the method is called
	 * @param key Key of the message to listen
	 * @param callback Listener adapter where is possible to run custom code
	 */

	public void setMessagesListener(Activity activity, String key, MessageListenerAdapter callback) {
		String id = activity.getClass().getName();
		mMap.putValue(key, id, callback);
	}
	
	/**
	 * Set a listener for the given key.
	 * Example:
	 * Mediator.getInstance().setMessageListener(mFragment,mKey,new MessageListenerAdapter() {
	 * 		@Override
	 *  	public void onMessageRecevied(){
	 *  	//CUSTOM CODE
	 *  	}
	 *  }
	 * @param activity The activity from which the method is called
	 * @param key Key of the message to listen
	 * @param callback Listener adapter where is possible to run custom code
	 */
	public void setMessagesListener(Fragment fragment, String key, MessageListenerAdapter callback) {
		String id = fragment.getClass().getName();
		mMap.putValue(key, id, callback);
	}
	
	/**
	 * Set a listener for the given key.
	 * Example:
	 * Mediator.getInstance().setMessageListener(mReceiver,mKey,new MessageListenerAdapter() {
	 * 		@Override
	 *  	public void onMessageRecevied(){
	 *  	//CUSTOM CODE
	 *  	}
	 *  }
	 * @param receiver The {@link BroadcastReceiver} from which the method is called
	 * @param key Key of the message to listen
	 * @param callback Listener adapter where is possible to run custom code
	 */
	public void setMessagesListener(BroadcastReceiver receiver, String key, MessageListenerAdapter callback) {
		String id = receiver.getClass().getName();
		mMap.putValue(key, id, callback);
	}

	/**
	 * When this method is called the Mediator invoke the listeners associated
	 * with the given id, if there are any.
	 * Example:
	 * mMediator.sendMessage("valore della key"," oggetto ");
	 * 
	 * @param key
	 *            Key
	 */
	public void sendMessage(String key) {
		Iterator<MessageListenerAdapter> mIter = mMap.getValues(key);
		while (mIter.hasNext())
			mIter.next().onMessageReceived();
	}

	/**
	 * When this method is called the Mediator invoke the listener associated
	 * with the given id, if there are any.
	 * 
	 * @param key
	 *            Key
	 * @param data
	 *            Object associated with the key
	 */
	public void sendMessageWithAttachedData(String key, Object data) {
		Iterator<MessageListenerAdapter> mIter = mMap.getValues(key);
		while (mIter.hasNext())
			mIter.next().onMessageReceviedWithData(data);
	}

	/**
	 * When this method is called the Mediator invoke the listener associated
	 * with the given id, if there are any.
	 * 
	 * @param key
	 *            Key
	 * @param data
	 *            Object associated with the key
	 */
	public void sendMessageWithAttachedData(String key, Bundle data) {
		Iterator<MessageListenerAdapter> mIter = mMap.getValues(key);
		while (mIter.hasNext())
			mIter.next().onMessageReceivedWithData(data);
	}

	/**
	 * When this method is called the Mediator invoke the listener associated
	 * with the given id, if there are any.
	 * 
	 * @param key
	 *            Key
	 * @param data
	 *            Object associated with the key
	 */
	public void sendMessageWithAttachedData(String key, String data) {
		Iterator<MessageListenerAdapter> mIter = mMap.getValues(key);
		while (mIter.hasNext())
			mIter.next().onMessageReceivedWithData(data);
	}

	/**
	 * When this method is called the Mediator invoke the listener associated
	 * with the given id, if there are any.
	 * 
	 * @param key
	 *            Key
	 * @param data
	 *            Object associated with the key
	 */
	public void sendMessageWithAttachedData(String key, int data) {
		Iterator<MessageListenerAdapter> mIter = mMap.getValues(key);
		while (mIter.hasNext())
			mIter.next().onMessageReceivedWithData(data);
	}
	
	/**
	 * When this method is called the Mediator invoke the listener associated
	 * with the given id, if there are any.
	 * 
	 * @param key
	 *            Key
	 * @param data
	 *            Object associated with the key
	 */
	public void sendMessageWithAttachedData(String key, int hours ,int minutes) {
		Iterator<MessageListenerAdapter> mIter = mMap.getValues(key);
		while (mIter.hasNext())
			mIter.next().onMessageReceivedWithData(hours,minutes);
	}

	
//	  public void removeMessageListener(String key,MessageListenerAdapter
//	  callback){
//	  mMap.removeValues(key, callback);
//	  }
	 

}
